<?php
/**
 * Created By: ST3
 * Created on 2015-11-10 16:07:56
 * Updated on 2015-11-10 16:09:37
 * author: yuyc@cheyun.com
 * coding: utf-8
*/

/**
 * ~~~
*	$config = [
*		'masterConfig' => [
*			'username' => 'root',
*			'password' => '1234',
*			'charset' => 'utf8',
*			'attributes' => [
*				PDO::ATTR_TIMEOUT => 10,
*			],
*		],
*
*		'masters' => [
*			['mysql:host=master1;dbname=xxx'],
*		],
*
*
*		'slaveConfig' => [
*			'username' => 'root',
*			'password' => '1234',
*			'charset' => 'utf8',
*			'attributes' => [
*				PDO::ATTR_TIMEOUT => 10,
*			],
*		],
*
*		'slaves' => [
*			['mysql:host=slave1;dbname=xxx'],
*			['mysql:host=slave1;dbname=xxx'],
*		],
*
*	];
 * ~~~
 */
define('ROOTPATH', dirname(__FILE__));
include ROOTPATH . '/config.php';

use \PDO;

class db {

	private static $_instance = null;
	protected $dbName = '';
	protected $dsn;
	protected $pdo;
	protected $master = false;

	public function __construct( array $config = array() ) {
		$this->config = Config::db();
		if ( $config ) {
			$this->config = array_merge($this->config, $config);
		}
	}

	public static function getInstance() {
		if (self::$_instance === null) {
			self::$_instance = new self();
		}
		return self::$_instance;
	}

	protected function initConnection($master = false) {
		if ( $this->pdo !== null) {
			return;
		}

		$this->master = $master;

		if ($this->master) {
			$this->pool = $this->config['masters'];
			$this->poolConfig = $this->config['masterConfig'];
		} else {
			$this->pool = $this->config['slaves'];
			$this->poolConfig = $this->config['slaveConfig'];
		}

		if (!isset($this->poolConfig['charset'])) {
			$this->poolConfig['charset'] = 'utf8';
		}

		$this->pdo = $this->openFromPool($this->pool);

		$this->pdo->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false);
		$this->pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
		$this->pdo->exec('SET character_set_connection='. $this->poolConfig['charset'] .';SET character_set_client='. $this->poolConfig['charset'] .';SET character_set_results='. $this->poolConfig['charset']);

	}

	protected function openFromPool(array $pool) {
		if ( empty($pool) ) {
			return null;
		}

		shuffle($pool);

		$this->dns = $pool[0];
		echo $this->dns . PHP_EOL;
		try {
			$pdo = new PDO($this->dns, $this->poolConfig['username'], $this->poolConfig['password'], $this->pool['attributes']);
			return $pdo;
		} catch (PDOException $e) {
			$this->outputError($e->getMessage());	
		}
	}

	public function fetchAll($sql, $params = array()) {
		$this->initConnection();
		try {
			$stm = $this->pdo->prepare($sql);
			if ($stm && $stm->execute($params)) {
				return $stm->fetchAll(\PDO::FETCH_ASSOC);
			}
		} catch (Exception $e) {
			$this->outputError($e->getMessage());
		}
	}

	public function fetchOne($sql, $params = array()) {
		$this->initConnection();
		try {
			$result = false;
			$stm = $this->pdo->prepare($sql);
			if ($stm && $stm->execute($params)) {
				$result = $stm->fetch(\PDO::FETCH_ASSOC);
			}
			return $result;
		} catch (Exception $e) {
			$this->outputError($e->getMessage());
		}
	}

	public function fetchColumn($sql, $params = array()) {
		$this->initConnection();
		$result = '';
		try {
			$stm = $this->pdo->prepare($sql);
			if ($stm && $stm->execute($params)) {
				$result = $stm->fetchColumn();
			}
			return $result;
		} catch (Exception $e) {
			$this->outputError($e->getMessage());
		}
	}

	public function insert($table, $params = array(), $returnLastId = true) {
		$this->initConnection(true);
		$_implode_field = '';
		$fields = array_keys($params);
		$_implode_field = implode(',', $fields);

		$_implode_value = '';
		foreach ($fields as $value) {
			$_implode_value .= ':'. $value.',';
		}
		$_implode_value = trim($_implode_value, ',');

		$sql = 'INSERT INTO ' . $table . '(' . $_implode_field . ') VALUES ('.$_implode_value.')';

		try {
			$stm = $this->pdo->prepare($sql);
			$result = $stm->execute($params);
			if ( $returnLastId ) {
				$result = $this->pdo->lastInsertId();
			}
			return $result;
		} catch (Exception $e) {
			$this->outputError($e->getMessage());
		}

	}

	public function update($table, $params = array(), $where = null) {
		$this->initConnection(true);
		$_implode_field = '';
		$_implode_field_arr = array();

		if ( empty($where) ) {
			return false;
		}

		$fields = array_keys($params);

		foreach ($fields as $key) {
			$_implode_field_arr[] = $key . '=' . ':'.$key;
		}

		$_implode_field = implode(',', $_implode_field_arr);
		$sql = 'UPDATE ' . $table . ' SET ' . $_implode_field . ' WHERE ' . $where;
		try {
			$stm = $this->pdo->prepare($sql);
			$result = $stm->execute($params);
			return $result;
		} catch (Exception $e) {
			$this->outputError($e->getMessage());
		}

	}

	public function delete($sql) {
		$this->initConnection(true);
		try {
			$result = $this->pdo->exec($sql);
			return $result;
		} catch (Exception $e) {
			$this->outputError($e->getMessage());
		}
	}


	public function exec($sql, $params = array()) {
		if (substr(strtolower($sql),0,6) != 'select') {
			$this->master = true;
		}

		$this->initConnection($this->master);

		try {
			$stm = $this->pdo->prepare($sql);
			$result = $stm->execute($params);
			return $result;
		} catch (Exception $e) {
			$this->outputError($e->getMessage());
		}
	}

	private function outputError($strErrMsg) {
		throw new Exception("MySQL Error: " . $strErrMsg);
	}

	public function __destruct() {
		$this->pdo = null;
		$this->master = false;
		$this->poolConfig = null;
		$this->config = null;
	}
}

$db = db::getInstance();

$sql = 'SELECT * FROM cy_link';
$result = $db->fetchAll($sql);
print_r($result);


/*
$sql = 'SELECT COUNT(*) FROM cy_link';
$count = $db->fetchColumn($sql);
echo $count;
*/

/*
$data = array(
	'siteid' => 1,
	'linktype' => 1,
	'name' => 'google',
	'url' => 'http://www.google.com',
	'listorder' => 0,
	'elite' => 0,
	'passed' => 1,
	'addtime' => time()
	);
$lastInsertId = $db->insert('cy_link', $data);
echo $lastInsertId;
*/

/*
$data = array(
	'siteid' => 1,
	'linktype' => 1,
	'name' => 'google',
	'url' => 'http://www.google.com',
	'listorder' => 0,
	'elite' => 0,
	'passed' => 1,
	'addtime' => time()
	);
$db->insert('cy_link', $data);
*/

/*
$sql = 'DELETE FROM cy_link WHERE linkid=4';

$result = $db->delete($sql);
var_dump($result);
*/





